package bdd;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import modele.Balade;
import modele.Docs;
import modele.Noeud;
import modele.Terme;

/**
 * 
 * @author Florence Delrieu & Coralie Micouin Classe pour recuperer les infos de
 *         la base et construire des objets
 * 
 */
public class GetBDD {

	/**
	 *  Singleton
	 */
	private static GetBDD INSTANCE = null;
	
	/**
	 *  Getter du singleton
	 * @return le singleton
	 */
	public static GetBDD getInstance() {
		if (GetBDD.INSTANCE == null) {
			GetBDD.INSTANCE = new GetBDD();
			GetBDD.INSTANCE.ouvreConnexion();
		}
		return GetBDD.INSTANCE;
	}

	private Connection conn;

	private GetBDD() {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();

		} catch (ClassNotFoundException ex) {
			System.err.println(ex.getMessage());
		} catch (IllegalAccessException ex) {
			System.err.println(ex.getMessage());
		} catch (InstantiationException ex) {
			System.err.println(ex.getMessage());
		}
	}

	private void ouvreConnexion() {
		try {
			String url = "jdbc:mysql://localhost/RepConn";
			conn = DriverManager.getConnection(url, "root", "");
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public void fermeConnexion() {
		try {
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Prend un terme en parametre et retourne une liste de Noeud
	 * contenant ce terme
	 * 
	 * @param terme
	 *            : terme recherche
	 * @return liste de noeuds avec le terme
	 */
	public ArrayList<Noeud> getNoeudsFromTerme(Terme terme) {
		ArrayList<Noeud> noeudsAvecTerme = new ArrayList<Noeud>();
		ArrayList<Integer> idNoeuds = terme.getIdNoeuds();

		for (int i = 0; i < idNoeuds.size(); i++) {
			noeudsAvecTerme.add(recupererNoeudFromId(idNoeuds.get(i)));
		}

		return noeudsAvecTerme;
	}

	public Balade construitBalade() {
		Balade b = new Balade();
		try {
//			ouvreConnexion();
			b.setDocuments(recupereDocuments());
			b.setNoeuds(recupererNoeuds());
			b.setTermes(recupererTermes());
//			fermeConnexion();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return b;
	}

	public ArrayList<Docs> recupereDocuments() throws SQLException {
		ArrayList<Docs> documents = new ArrayList<Docs>();
		Statement st = conn.createStatement();
		ResultSet rs = st.executeQuery("SELECT idDocument, nomDocument FROM Document");

		while (rs.next()) {
			Docs doc = new Docs(rs.getString("nomDocument"));
			documents.add(rs.getInt("idDocument"), doc);
		}
		return documents;
	}

	public ArrayList<Noeud> recupererNoeuds() throws SQLException {
		ArrayList<Noeud> noeuds = new ArrayList<Noeud>();
		Statement st = conn.createStatement();
		ResultSet rs = st
				.executeQuery("SELECT idNoeud, xPath, longueur, idDocument FROM Noeud");

		while (rs.next()) {
			noeuds.add(new Noeud(rs.getInt("idDocument"),
					rs.getString("xPath"), rs.getInt("idNoeud"), rs
							.getInt("longueur")));
		}
		return noeuds;
	}

	public ArrayList<Terme> recupererTermes() throws SQLException {
		ArrayList<Terme> termes = new ArrayList<Terme>();
		Statement st = conn.createStatement();
		ResultSet rs = st
				.executeQuery("SELECT idTerme, terme, positions, frequences, tf, idf, score FROM Terme");

		while (rs.next()) {
			termes.add(new Terme(rs.getString("terme"), rs.getInt("idTerme"),
					rs.getString("positions"), rs.getString("frequences"), rs
							.getString("idf"), rs.getString("tf"), rs.getString("score")));
		}
		return termes;
	}

	/**
	 * Construit et retourne un objet de type Terme a partir d'un
	 * terme textuel en accedant aux infos dans la base
	 * 
	 * @param terme
	 *            : texte du terme a construire
	 * @return un Terme
	 */
	public Terme recupererTermeFromString(String terme) {
		Terme t = null;
//		ouvreConnexion();
		try {
			Statement st = conn.createStatement();
			ResultSet rs = st
					.executeQuery("SELECT idTerme, terme, positions, frequences, tf, idf, score FROM Terme WHERE terme = \"" + terme + "\"");
			if (rs.next()) {
				t = new Terme(rs.getString("terme"), rs.getInt("idTerme"),
						rs.getString("positions"), rs.getString("frequences"),
						rs.getString("idf"), rs.getString("tf"), rs.getString("score"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
//		fermeConnexion();
		return t;

	}

	/**
	 * Construit et retourne un objet de type Noeud a partir d'un id
	 * de noeud en accedant aux infos dans la base
	 * 
	 * @param idNoeud
	 *            : id du noeud a construire
	 * @return un Noeud
	 */
	public Noeud recupererNoeudFromId(int idNoeud) {
		Noeud n = null;
		
//		ouvreConnexion();
		try {
			Statement st = conn.createStatement();
			ResultSet rs = st
					.executeQuery("SELECT idNoeud, xPath, longueur, idDocument FROM Noeud WHERE idNoeud = " + idNoeud);
			if (rs.next()) {
				n = new Noeud(rs.getInt("idDocument"),
						rs.getString("xPath"), rs.getInt("idNoeud"), rs
						.getInt("longueur"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
//		fermeConnexion();

		return n;

	}
	

	public Docs recupererDocsFromId(int idDocs) {
		Docs d = null;
		
//		ouvreConnexion();
		try {
			Statement st = conn.createStatement();
			ResultSet rs = st
					.executeQuery("SELECT idDocument, nomDocument FROM Document WHERE idDocument = " + idDocs);
			if (rs.next()) {
				d = new Docs(rs.getString("nomDocument"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
//		fermeConnexion();

		return d;

	}
	

	public int getNombreNoeud() {	
		int nombreDeNoeuds = 0 ;
//		ouvreConnexion();
		try {
			Statement st = conn.createStatement();
			ResultSet rs = st.executeQuery("SELECT COUNT(*) AS nbNoeuds FROM Noeud;");
			if (rs.next()) {
				nombreDeNoeuds = rs.getInt("nbNoeuds");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
//		fermeConnexion();

		return nombreDeNoeuds;

	}

	public void testGetNombreNoeud() {
		System.out.println(getNombreNoeud());
	}
	
	public void testRecupererBalades() {
		Balade b = construitBalade();
		b.afficher();
	}

	public static void main(String[] args) {
		GetBDD getbdd = GetBDD.getInstance();
		//getbdd.testRecupererBalades();
		getbdd.testGetNombreNoeud();
		getbdd.fermeConnexion();
	}
}
